﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Client.Data.Services;
using System.Reflection;

namespace Kocic.RepositoryManagement.Crm4
{
    /// <summary>
    /// Allows CRM data manager objects to re-use a single instance of a CRM data context for CRM 4.0.
    /// </summary>
    /// <typeparam name="TContext">The type of the CRM data object context to use within the execution context of this instance.</typeparam>
    public class XrmExecutionContext<TContext> : DataSourceExecutionContext<TContext>
        where TContext : CrmDataContext, new()
    {
        /// <summary>
        /// Creates an instance of the XrmExecutionContext class.
        /// </summary>
        public XrmExecutionContext()
        {

        }

        /// <summary>
        /// Creates an instance of the XrmExecutionContext class.
        /// </summary>
        /// <param name="connectionString">The CRM connection string used to initalize a connection to the CRM server.</param>
        public XrmExecutionContext(string connectionString)
            : base(connectionString)
        {

        }

        /// <summary>
        /// Initializes the CRM data context by utilizing reflection to pass in the connection string needed to connect to CRM, to the constructor of the instance of TContext.
        /// </summary>
        protected override void InitializeDataSource()
        {
            //Gets the type of the generic context defined. Uses reflection to invoke the parameterized constructor to pass in the connection string needed to connect to CRM.
            Type t = typeof(TContext);
            ConstructorInfo contextConstructor = t.GetConstructor(new Type[] { typeof(string) });
            object contextClassObject = contextConstructor.Invoke(new object[] { this.DataString });

            this.DataSource = contextClassObject as TContext;

            ExecutionContext = this;
            this.Disposed = false;
        }


        /// <summary>
        /// Disposes unmanaged resources.
        /// </summary>
        /// <param name="disposing">Value indicating if to invoke the method from the IDisposable.Dispose implementation or from the finalizer.</param>
        protected override void Dispose(Boolean disposing)
        {
            if (disposing)
            {
                if (this.Disposed)
                    return;

                ExecutionContext = null;
                this.DataSource = null;
                this.Disposed = true;
            }
        }
    }
}